﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows;

namespace WWLauncher.Upgrade
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private readonly List<string> coveredFiles = new();  //已经被替换的文件
        private readonly Downloader downloader = new();
        public MainWindow()
        {

            InitializeComponent();
            Loaded += MainWindow_Loaded;

            //var v = new Version("1.11.4");
            //var ww = new Version("1.1.4");
            //var w = v > ww;


            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            try
            {
                FileVersionInfo versionInfo;
#if DEBUG
                versionInfo = FileVersionInfo.GetVersionInfo("WWLauncher-D.exe");
#else
                versionInfo= FileVersionInfo.GetVersionInfo("WWLauncher.exe");
#endif

                vm.Version = versionInfo.ProductVersion;
            }
            catch
            {
                vm.Version = "0.0.0.0";
            }



        }

        private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            var info = await downloader.GetServerInfo(vm.Version);

            //杀掉主程序开始更新（也可在此处添加弹窗询问是否更新）
            try
            {
                Process.GetProcessesByName("WWLauncher-D").ToList().ForEach(p => p.Kill());
            }
            catch { }
            try
            {
                Process.GetProcessesByName("WWLauncher").ToList().ForEach(p => p.Kill());
            }
            catch { }


            vm.Information = info.Information;
            vm.PackageUrl = info.PackageUrl;
            vm.PackageVersion = info.PackageVersion;

            vm.Information = string.Empty;

        }



        private async Task DoUpdate()
        {
            //解压部分
            ZipFile.ExtractToDirectory(vm.PackageVersion + ".zip", downloader.UnzipDirect, Encoding.GetEncoding("GB2312"), true);

            string[] updateFiles = Directory.GetFiles(downloader.UnzipDirect, "*", SearchOption.AllDirectories);
            if (updateFiles.Length == 0)
                return;  //解压完是空的

            //备份部分
            if (Directory.Exists(downloader.BackupDirect))
                Directory.Delete(downloader.BackupDirect, true);
            Directory.CreateDirectory(downloader.BackupDirect);
            if (!await BackupFiles(updateFiles))
            {
                if (Directory.Exists(downloader.BackupDirect))
                    Directory.Delete(downloader.BackupDirect, true);
                return;
            }

            //替换部分
            if (!await UpdateFiles(updateFiles))
            {
                await RollbackFiles();
                return;
            }


            await Task.Delay(200);

            if (Directory.Exists(downloader.DownloadDirect))
                Directory.Delete(downloader.DownloadDirect, true);
            if (Directory.Exists(downloader.BackupDirect))
                Directory.Delete(downloader.BackupDirect, true);
        }


        #region -- 备份 --

        private async Task<bool> BackupFiles(string[] files)
        {
            vm.Maximum = files.Length;
            for (int i = 0; i < files.Length; i++)
            {
                vm.Message = $"正在备份旧文件，第{i + 1}个，共{files.Length}个";
                vm.ProgressBarValue = i;

                string relativeFileName = files[i][downloader.UnzipDirect.Length..];
                if (relativeFileName[0] == '\\')
                    relativeFileName = relativeFileName[1..];
                string originalFileName = Path.Combine(Environment.CurrentDirectory, relativeFileName);
                string toName = Path.Combine(downloader.BackupDirect, relativeFileName);
                string toDir = Path.GetDirectoryName(toName)!;
                if (!Directory.Exists(toDir))
                    Directory.CreateDirectory(toDir);

                if (!File.Exists(originalFileName))
                    continue;

                try
                {
                    File.Copy(originalFileName, toName, true);
                }
                catch (Exception)
                {
                    MessageBox.Show($"{toName.Substring(Environment.CurrentDirectory.Length)}文件备份失败，建议手动更新", "错误");
                }
                await Task.Delay(30);
            }
            vm.ProgressBarValue = files.Length;
            await Task.Delay(30);
            return true;
        }

        #endregion -- 备份 --

        #region -- 替换 --

        private async Task<bool> UpdateFiles(string[] files)
        {
            for (int i = 0; i < files.Length; i++)
            {
                vm.Message = $"正在更新文件，第{i + 1}个，共{files.Length}个";
                vm.ProgressBarValue = i;

                if (files[i].Contains("自动更新程序"))
                {
                    continue;  //自己不能被替换，跳过自己，由主程序替换
                }

                string relativeFileName = files[i][downloader.UnzipDirect.Length..];
                if (relativeFileName[0] == '\\')
                    relativeFileName = relativeFileName[1..];
                string toName = Path.Combine(Environment.CurrentDirectory, relativeFileName);
                string toDir = Path.GetDirectoryName(toName)!;
                if (!Directory.Exists(toDir))
                    Directory.CreateDirectory(toDir);
                try
                {
                    File.Copy(files[i], toName, true);
                }
                catch
                {
                    MessageBox.Show($"更新失败，{toName.Substring(Environment.CurrentDirectory.Length)}无法被替换，即将回滚更新", "错误");
                    return false;
                }
                coveredFiles.Add(toName);
                await Task.Delay(30);
            }
            vm.ProgressBarValue = files.Length;
            await Task.Delay(30);
            return true;
        }

        #endregion -- 替换 --

        #region -- 回滚 --

        private async Task RollbackFiles()
        {
            vm.Message = $"更新失败，即将回滚更新";
            await Task.Delay(500);
            for (int i = coveredFiles.Count - 1; i >= 0; i--)
            {
                vm.Message = $"更新失败，正在回滚更新，第{i}个，共{coveredFiles.Count}个";
                vm.ProgressBarValue = i;

                string relativeFileName = coveredFiles[i][Environment.CurrentDirectory.Length..];
                if (relativeFileName[0] == '\\')
                    relativeFileName = relativeFileName[1..];
                string fromName = Path.Combine(downloader.BackupDirect, relativeFileName);
                try
                {
                    File.Copy(fromName, coveredFiles[i], true);
                }
                catch (Exception)
                {
                    MessageBox.Show("回滚失败", "错误");
                }
                await Task.Delay(30);
            }
        }

        #endregion -- 回滚 --

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            await DoUpdate();
            try
            {
                Process.Start(new ProcessStartInfo("WWLauncher-D.exe") { UseShellExecute = false });
            }
            catch
            {
                // ignored
            }
            try
            {
                Process.Start(new ProcessStartInfo("WWLauncher.exe") { UseShellExecute = false });
            }
            catch
            {
                // ignored
            }
            await downloader.DownloadPackage();
        }
    }
}
